import json  # 处理JSON数据的编码和解码
from datetime import datetime  # 处理日期和时间

from django.http import JsonResponse  # 返回JSON格式的HTTP响应
from django.shortcuts import render
from django.views import View  # Django的类视图基类

# 模型SysMenu（菜单）、SysRoleMenu（角色菜单关联表）和序列化器SysMenuSerializer
from menu.models import SysMenu, SysMenuSerializer, SysRoleMenu


class TreeListView(View):
    # 构造菜单树,将扁平的菜单列表转换为树形结构
    def buildTreeMenu(self, sysMenuList):
        # 创建 resultMenuList 空列表，并指定这个列表未来只能装 SysMenu 类型的对象
        resultMenuList: list[SysMenu] = list()

        for menu in sysMenuList:  # 遍历每个菜单项 menu
            for e in sysMenuList:  # 对于每个 menu，再次遍历所有菜单项 e，寻找其子节点

                # 如果 menu 没有 children 属性，动态添加一个空列表
                if e.parent_id == menu.id:
                    if not hasattr(menu, "children"):
                        menu.children = list()
                    menu.children.append(e)  # 将子节点 e 添加到 menu.children 中

            # 如果 menu 是根节点（parent_id == 0），加入结果列表
            if menu.parent_id == 0:
                resultMenuList.append(menu)
        return resultMenuList

    # 处理 GET 请求，返回树形菜单数据
    def get(self, request):
        # 从数据库获取所有菜单并按 order_num 排序
        menuQuerySet = SysMenu.objects.order_by("order_num")
        # 调用 buildTreeMenu 构建树形结构
        sysMenuList: list[SysMenu] = self.buildTreeMenu(menuQuerySet)

        # 使用序列化器将每个菜单对象转为JSON格式
        serializerMenuList: list[SysMenuSerializer] = list()
        for sysMenu in sysMenuList:
            serializerMenuList.append(SysMenuSerializer(sysMenu).data)
        return JsonResponse({'code': 200, 'treeList': serializerMenuList})


class SaveView(View):
    # 处理新增或修改菜单的 POST 请求
    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        if data['id'] == -1:  # 是新增
            obj_sysMenu = SysMenu(name=data['name'],  # 创建新 SysMenu 对象，设置字段值
                                  icon=data['icon'],
                                  parent_id=data['parent_id'],
                                  order_num=data['order_num'],
                                  path=data['path'],
                                  component=data['component'],
                                  menu_type=data['menu_type'],
                                  perms=data['perms'],
                                  remark=data['remark'])

            obj_sysMenu.create_time = datetime.now().date()  # 设置 create_time 为当前日期
            obj_sysMenu.save()
        else:  # 是修改
            obj_sysMenu = SysMenu(id=data['id'],  # 根据提交的 id 创建对象，覆盖所有字段
                                  name=data['name'],
                                  icon=data['icon'],
                                  parent_id=data['parent_id'],
                                  order_num=data['order_num'],
                                  path=data['path'],
                                  component=data['component'],
                                  menu_type=data['menu_type'],
                                  perms=data['perms'],
                                  remark=data['remark'],
                                  create_time=data['create_time'],
                                  update_time=data['update_time'])

            obj_sysMenu.update_time = datetime.now().date()  # 设置 update_time 为当前日期
            obj_sysMenu.save()
        return JsonResponse({'code': 200})


# 菜单基本操作
class ActionView(View):
    # 根据 ID 获取单个菜单的详细信息
    def get(self, request):
        id = request.GET.get("id")  # 从URL参数获取 id
        menu_object = SysMenu.objects.get(id=id)  # 查询数据库获取对应菜单对象
        return JsonResponse({'code': 200,  # 序列化后返回JSON数据
                             'menu': SysMenuSerializer(menu_object).data})

    # 删除指定菜单
    def delete(self, request):
        id = json.loads(request.body.decode("utf-8"))

        # 检查是否有子菜单存在，若有则返回错误
        if SysMenu.objects.filter(parent_id=id).count() > 0:
            return JsonResponse({'code': 500, 'msg': '请先删除子菜单！'})
        else:
            SysRoleMenu.objects.filter(menu_id=id).delete()  # 删除关联的 SysRoleMenu 记录
            SysMenu.objects.get(id=id).delete()  # 删除菜单本身
            return JsonResponse({'code': 200})
